//
//  AppDelegate.swift
//  GLUZSwift
//
//  Created by xyanl on 2025/3/6.
//

import UIKit
import IQKeyboardManagerSwift
import IQKeyboardToolbarManager
import Localize_Swift
import ZPNs
import SwiftyFitsize
import SwiftyUserDefaults
import AppTrackingTransparency
import AdSupport
import Reusable

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        /**
         打包时验证环境
         
         切换 Scheme
         GLUZSwift 是线上正式版
         GLUZSwift-DEBUG 线下测试版
         
         */
#if DEBUG
//        SystemEnvManager.shared.envType = .development
        SystemEnvManager.shared.envType = .release
#else
        SystemEnvManager.shared.envType = .release
#endif
        xLog("[APP] App 名字: \(Bundle.sg.appDisplayName)")
        xLog("[APP] 当前版本号: \(Bundle.sg.appVersion)")
        xLog("[APP] 当前环境: \(SystemEnvManager.shared.isRelease ? "线上": "测试")")

        // 初始化网络监控
        // NetworkMonitor.shared.startListening()
        
        // 配置数据库
        RealmTools.configRealm(tableName: "GLUZ_Realm")
        // 打印出数据库地址
        xLog("RealmTools 存储路径：\(RealmTools.fileURL?.path ?? "没有路径")")
        
        
        initAliOSS()
        initNavBarAppearence()
        initIQKeyboardManager()
        initWechatManager()
        initZPNs()
        initZIMKit()
        
        DispatchQueue.main.asyncAfter(wallDeadline: .now() + 10) {
            self.initAppTrackingTransparency()
        }
        // Swift 优雅的适配大小 https://www.jianshu.com/p/d0463a042543
        SwiftyFitsize.reference(width: 414)
        
        initWindow()
        
        return true
    }
    
    private func handleUrl(_ url: URL) -> Bool {
        // 获取路径和查询参数
        xLog("[scheme] url \(url.absoluteString)")
        xLog("[scheme] 参数 \(url.sg.pathComponents! as NSDictionary)")
        
        guard let pathComponents = url.sg.pathComponents else {
            return false
        }
        
        
        if url.absoluteString.contains("url=") {
            let path = NSString(string: url.absoluteString).components(separatedBy: "url=").last!
            let uRl = SystemEnvManager.shared.shopUrl + path + H5UrlManager.urlParameter()
            currentController?.push(BaseWebViewController(url: uRl, isNavBarHide: true))
            return true
        }
        
        // h5吊起app分享url scheme
        // gluzshop://page?url=/pages/details/shopDetail?bid=465&type=2&offerId=&offer_price=
        // type 5:注册,
        if (currentController?.isKind(of: LoginRegisterController.self) == true) { return true }
        if let jump = pathComponents["jump"] {
            if jump.hasPrefix("register?topId=") {
                // 获取邀请码
                let topId = jump.replacingOccurrences(of: "register?topId=", with: "")
                Defaults[\.inviterCode] = topId
                if !UserProfile.isLogin {
                    // 未登录跳转到注册页
                    currentController?.push(LoginRegisterController())
                    return true
                }
            }
        }
        
        return true
    }
}

private extension AppDelegate {
    func initWindow() {
        
        window = UIWindow(frame: UIScreen.main.bounds)
        // 背景色
        window?.backgroundColor = .white
        
        if Bundle.sg.isFirstLaunch() {
            window?.rootViewController = LaunchController()
        } else {
            let token = UserProfile.token
            let username = UserProfile.username
            let usernameru = UserProfile.usernameRu
            xLog("Token: \(token) username:\(username) usernameRu:\(usernameru)")
            if token.isEmpty {
                // 未登录，默认中文
                // LanguageManager.setLanguage(.zh)
                window?.rootViewController = BaseNavigationController(rootViewController: LoginMainController())
                
            } else {
                // 根据注册时选中的国家类型，同步本地化语言
                LanguageManager.setLanguage(UserProfile.country)
                window?.rootViewController = BaseTabBarController()
                loginZego { [self] data in
                    DispatchQueue.main.async {
                        xLog("[ZEGO] 用户登录 \(data ?? [:])")
                        let code = (data?["code"] as? Int) ?? -1
                        xLog("[ZEGO] code \(code)")
                        if code == 0 {
                            LanguageManager.setLanguage(UserProfile.country)
                            if var vc = self.window?.rootViewController, !(vc is BaseTabBarController) {
                                vc = BaseTabBarController()
                            }
                            
                        } else {
                            // 登录失败
                            YLHUD.showMessage("登录失败".localized() + "(\(code))")
                            self.window?.rootViewController = BaseNavigationController(rootViewController: LoginMainController())
                        }
                    }
                }
                
            }
        }
        
        // 渲染出页面
        window?.makeKeyAndVisible()
        xLog("渲染出页面")
    }
    
    func initAliOSS() {
        let config: AliOSSConfig = AliOSSConfig()
        config.accessKey = "LTAI5tJzTZBzFkjYiLTmn1Ca"
        config.secretKey = "M4LiEM0ZnUxtT0dV537nHL33ODjw7q"
        config.bucketName = "gluz-oss"
        config.endpoint = "https://oss-accelerate.aliyuncs.com"
        config.domainName = "https://gluz-oss.oss-accelerate.aliyuncs.com"
        
        let ymd = Date.sg.timeString(formatter: "yyyyMMdd")
        config.folderName = "uploads/" + ymd// AliOSSConfig().defaultPath()
        // config.folderName = "Test/xyanl"
        AliOSSUtil.shared.initClient(config: config)
        //    OSS 上传
        //    AccessKey ID:   LTAI5tJzTZBzFkjYiLTmn1Ca
        //    AccessKey Secret:  M4LiEM0ZnUxtT0dV537nHL33ODjw7q
        //    Bucket名称:  gluz-oss
        //    Endpoint: oss-cn-beijing.aliyuncs.com
        //    CDN地址: https://gluz-oss.oss-cn-beijing.aliyuncs.com
        //    保存文件名: /uploads/{year}{mon}{day}/{filemd5}{.suffix}
    }
    
    /// 初始化 NavigationBar
    func initNavBarAppearence() {
        VHLNavigation.hook()
        VHLNavigation.def.navBarShadowImageHidden = true
        // 忽略掉控制器
        VHLNavigation.def.addIgnoreVCName("JFPopupController")
        
        VHLNavigation.def.addIgnoreVCName("PhotoPickerViewController")
        VHLNavigation.def.addIgnoreVCName("PhotoPreviewViewController")
        VHLNavigation.def.addIgnoreVCName("CameraViewController")
    }
    
    // TODO: - IQKeyboardManager 初始化
    func initIQKeyboardManager() {
        let manager = IQKeyboardManager.shared
        // 控制整个功能是否启用。
        manager.isEnabled = true
        manager.keyboardConfiguration.overrideAppearance = true
        // 控制点击背景是否收起键盘
        manager.resignOnTouchOutside = true
        //        // 控制键盘上的工具条文字颜色是否用户自定义。  注意这个颜色是指textfile的tintcolor
        //        manager.toolbarConfiguration.useTextFieldTintColor = true
        //        // 中间位置是否显示占位文字(默认是true)
        //        manager.toolbarConfiguration.placeholderConfiguration.showPlaceholder = false
        //        // 设置占位文字的字体大小
        //        manager.toolbarConfiguration.placeholderConfiguration.font = .boldSystemFont(ofSize: 18)
        //        // 控制是否显示键盘上的工具条。
        //        manager.enableAutoToolbar = false
        //        // 输入框距离键盘的距离
        //        manager.keyboardDistanceFromTextField = 10.0
        
        IQKeyboardToolbarManager.shared.isEnabled = false
        // 控制键盘上的工具条文字颜色是否用户自定义。  注意这个颜色是指textfile的tintcolor
        IQKeyboardToolbarManager.shared.toolbarConfiguration.useTextInputViewTintColor = true
        // 中间位置是否显示占位文字(默认是true)
        IQKeyboardToolbarManager.shared.toolbarConfiguration.placeholderConfiguration.showPlaceholder = false
        // 设置占位文字的字体大小
        IQKeyboardToolbarManager.shared.toolbarConfiguration.placeholderConfiguration.font = .boldSystemFont(ofSize: 18)
    }
    
    /// 初始化微信
    func initWechatManager() {
        WechatManager.shared.appID = KeyCenter.WeChat.appID
        WechatManager.shared.appSecret = KeyCenter.WeChat.appSecret
        WechatManager.shared.universalLink = KeyCenter.WeChat.universalLink
        WechatManager.shared.state = "GLUZSwift"
        
        let success = WechatManager.registerApp()
        xLog("[微信] 注册 \(success ? "成功": "失败")")
        
    }
    
    func initZPNs() {
        ZPNs.shared().registerAPNs()
    }
    
    func initZIMKit() {
        let config = ZIMKitConfig()
        
        // 是否为沙盒环境，默认值为 true。如需将您的应用程序发布到 TestFlight 或 App Store，请在开始构建之前将 isSandboxEnvironment 设置为 false。如需进行本地调试，请将其设置为 true。当 notifyWhenAppRunningInBackgroundOrQuit 为 false 时，请忽略此设置。
        // 当 App 在后台运行或用户已退出 App 时，如果不需要接收呼叫邀请通知，请将 notifyWhenAppRunningInBackgroundOrQuit 设置为false。
        // certificateIndex, 后台可以设置 2 张不同的证书,在这里进行切换
        
#if DEBUG
        let callInvitationConfig = ZegoUIKitPrebuiltCallInvitationConfig(
            notifyWhenAppRunningInBackgroundOrQuit: true,
            isSandboxEnvironment: true,
            certificateIndex: .firstCertificate
        )
#else
        let callInvitationConfig = ZegoUIKitPrebuiltCallInvitationConfig(
            notifyWhenAppRunningInBackgroundOrQuit: true,
            isSandboxEnvironment: false,
            certificateIndex: .firstCertificate
        )
#endif
        config.callPluginConfig = ZegoCallPluginConfig(
            invitationConfig: callInvitationConfig,
            resourceID: "gluz_call_resources"
        )
        config.bottomConfig.smallButtons = [.audio, .emoji, .picture, .expand, .voiceCall]
        config.bottomConfig.expandButtons = [.takePhoto, .file, .videoCall]
        
        ZIMKit.initWith(
            appID: KeyCenter.IM.appID,
            appSign: KeyCenter.IM.appSign,
            config: config
        )
        ZIMKit.registerZIMKitDelegate(self)
    }
    
    
    func initAppTrackingTransparency() {
        ATTrackingManager.requestTrackingAuthorization { status in
            switch status {
            case .notDetermined:
                xLog("[ATTrackingManager] 用户未做选择或未弹窗IDFA")
                //用户未做选择或未弹窗IDFA
                //请求弹出用户授权框，只会在程序运行是弹框1次，除非卸载app重装，通地图、相机等权限弹框一样
                // self.initAppTrackingTransparency()
                
            case .restricted:
                xLog("[ATTrackingManager] 限制状态无法选择")
                
            case .denied:
                xLog("[ATTrackingManager] 用户拒绝IDFA")
                
            case .authorized:
                let idfaString = ASIdentifierManager.shared().advertisingIdentifier.uuidString
                xLog("[ATTrackingManager] 用户允许IDFA: \(idfaString)")
                
            @unknown default:
                fatalError()
            }
        }
    }
}


extension AppDelegate {
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // 注册通知
        xLog("【APNS】deviceToken： \(deviceToken.base64EncodedString())")
        /// 6.获取 APNs 设备 Token , 必需 - 设置设备令牌, 离线推送需要
        ZegoUIKitPrebuiltCallInvitationService.setRemoteNotificationsDeviceToken(deviceToken)
#if DEBUG
        ZPNs.shared().setDeviceToken(deviceToken, isProduct: false)
#else
        ZPNs.shared().setDeviceToken(deviceToken, isProduct: true)
#endif
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: any Error) {
        // 注册失败
        xLog("【APNS】注册失败 deviceToken： \(error.localizedDescription)")
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        xLog("【APNS】didReceiveRemoteNotification： \(userInfo)")
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        // 确保在主线程执行
        DispatchQueue.main.async {
            self.pasteboard()
        }
    }
}


private extension AppDelegate {
    
    // 获取剪切板,放在异步线程
    func pasteboard() {
        
        let board = UIPasteboard.general
        guard let content = board.string else { return }
        // 获取路径和查询参数
        xLog("[剪切板] content \(content)")
        
        if content.hasPrefix("url=") {
            let url = content.replacingOccurrences(of: "url=", with: "")
            board.string = ""
            DispatchQueue.main.async {
                currentController?.push(BaseWebViewController(url: SystemEnvManager.shared.shopUrl + "?" + url + H5UrlManager.urlParameter(), isNavBarHide: true))
            }
            return
        }
        
        // h5吊起app分享url scheme
        // gluzshop://page?url=/pages/details/shopDetail?bid=465&type=2&offerId=&offer_price=
        // type 5:注册,
        if content.hasPrefix("jump=register?") {
            // jump=register?topId=94876930&type=1
            // 获取邀请码
            let paramet = content.replacingOccurrences(of: "jump=register?", with: "")
            
            let parameterArr = paramet.split(separator: "&")
            var parameterDic: [String: String] = [:]
            parameterArr.forEach { subString in
                if subString.contains("=") {
                    let kv = subString.split(separator: "=")
                    if let key = kv.first, let value = kv.last {
                        parameterDic[String(key)] = String(value)
                    }
                }
            }
            
            if let inviterCode = parameterDic["topId"] {
                board.string = ""
                Defaults[\.inviterCode] = inviterCode
                if !UserProfile.isLogin {
                    DispatchQueue.main.async {
                        // 检查当前控制器类型，避免重复跳转
                        if (currentController?.isKind(of: LoginRegisterController.self) == true) { return }
                        // 未登录跳转到注册页
                        currentController?.push(LoginRegisterController())
                    }
                    return
                }
            }
        }
        
    }
}

// MARK: - 微信
extension AppDelegate {
    
    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        /// 微信 支付
        if url.absoluteString.contains(KeyCenter.WeChat.appID) {
            return WechatManager.shared.handleOpenURL(url)
        }
        
        /// 支付宝 支付
        if url.host == "safepay" {
            DispatchQueue.global(qos: .userInitiated).async {
                // 跳转支付宝客户端进行支付，处理支付结果
                // 处理支付宝客户端返回的 URL（在 App 被强行停止运行时，通过这个方法获取支付结果）。
                AlipaySDK.defaultService().processOrder(withPaymentResult: url, standbyCallback: nil)
                
                // 授权跳转支付宝钱包进行支付，处理支付结果
                AlipaySDK.defaultService().processAuth_V2Result(url) { result in
                    xLog("[支付宝] 授权跳转处理支付结果： \(result ?? [:])")
                }
            }
        }
        
        return true
    }
    
    // iOS9以上会优先走这个方法
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
        xLog("options: [UIApplication.OpenURLOptionsKey : Any]")
        
        if url.scheme == "gluzshop" {
            // 处理URL
            return handleUrl(url)
        }
        
        /// 微信 支付
        if url.absoluteString.contains(KeyCenter.WeChat.appID) {
            return WechatManager.shared.handleOpenURL(url)
        }
        
        /// 支付宝 支付
        if url.host == "safepay" {
            DispatchQueue.global(qos: .userInitiated).async {
                // 跳转支付宝客户端进行支付，处理支付结果
                // 处理支付宝客户端返回的 URL（在 App 被强行停止运行时，通过这个方法获取支付结果）。
                AlipaySDK.defaultService().processOrder(withPaymentResult: url, standbyCallback: nil)
                
                // 授权跳转支付宝钱包进行支付，处理支付结果
                AlipaySDK.defaultService().processAuth_V2Result(url) { result in
                    xLog("[支付宝] 授权跳转处理支付结果： \(result ?? [:])")
                }
            }
        }
        
        return true
    }
    
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
        
        if (userActivity.webpageURL?.absoluteString.contains(KeyCenter.WeChat.appID)) != nil {
            return WechatManager.shared.handleOpenUniversalLink(userActivity: userActivity)
        }
        
        return true
    }
    
}

extension AppDelegate: ZIMKitDelegate {
    func onTotalUnreadMessageCountChange(_ totalCount: UInt32) {
        xLog("[IM] 未读消息总数 totalCount = \(totalCount)")
        DispatchQueue.main.async {
            UIApplication.shared.applicationIconBadgeNumber = Int(totalCount)
            BaseTabBarController.updateTabBarBadgeValue(index: 2, count: Int(totalCount))
        }
    }
}

extension AppDelegate {
    func loginZego(callback: PluginCallBack?) {
        let userName = LanguageManager.currentLanguageToText(UserProfile.username, UserProfile.usernameRu)
        let userId = String(UserProfile.userId)
        let avatar = UserProfile.avatar
        let info = [
            "userId": userId,
            "userName": userName,
            "avatar": avatar,
        ]
        xLog("[IM] 登录 \( info as NSDictionary)")
        
        // 登录视频通话
        // 是否为沙盒环境，默认值为 true。如需将您的应用程序发布到 TestFlight 或 App Store，请在开始构建之前将 isSandboxEnvironment 设置为 false。如需进行本地调试，请将其设置为 true。当 notifyWhenAppRunningInBackgroundOrQuit 为 false 时，请忽略此设置。
        // 当 App 在后台运行或用户已退出 App 时，如果不需要接收呼叫邀请通知，请将 notifyWhenAppRunningInBackgroundOrQuit 设置为false。
#if DEBUG
        let config = ZegoUIKitPrebuiltCallInvitationConfig(
            notifyWhenAppRunningInBackgroundOrQuit: true,
            isSandboxEnvironment: true,
            certificateIndex: .firstCertificate
        )
#else
        let config = ZegoUIKitPrebuiltCallInvitationConfig(
            notifyWhenAppRunningInBackgroundOrQuit: true,
            isSandboxEnvironment: false,
            certificateIndex: .firstCertificate
        )
#endif
        config.translationText = ZegoTranslationText(language: LanguageManager.isCountryCN ? .CHS: .RU)
        // 用户登录
        ZegoUIKitPrebuiltCallInvitationService.shared.initWithAppID(KeyCenter.IM.appID, appSign: KeyCenter.IM.appSign, userID: userId, userName: userName, userAvatar: avatar, config: config, callback: callback)
    }
}


// MARK: -ZegoUIKitPrebuiltCallInvitationServiceDelegate
extension AppDelegate: ZegoUIKitPrebuiltCallInvitationServiceDelegate {
    func requireConfig(_ data: ZegoCallInvitationData) -> ZegoUIKitPrebuiltCallConfig {
        if data.type == .voiceCall {
            if data.invitees?.count ?? 0 > 1 {
                let config = ZegoUIKitPrebuiltCallConfig.groupVoiceCall()
                return config
            } else {
                let config = ZegoUIKitPrebuiltCallConfig.oneOnOneVoiceCall()
                return config
            }
        } else {
            if data.invitees?.count ?? 0 > 1 {
                let config = ZegoUIKitPrebuiltCallConfig.groupVideoCall()
                return config
            } else {
                let config = ZegoUIKitPrebuiltCallConfig.oneOnOneVideoCall()
                return config
            }
        }
    }
    
    func onIncomingCallDeclineButtonPressed() {
        
    }
    func onIncomingCallAcceptButtonPressed() {
        
    }
    func onOutgoingCallCancelButtonPressed() {
        
    }
    
    func onIncomingCallReceived(_ callID: String, caller: ZegoCallUser, callType: ZegoCallType, callees: [ZegoCallUser]?) {
        
    }
    func onIncomingCallCanceled(_ callID: String, caller: ZegoCallUser) {
        
    }
    func onOutgoingCallAccepted(_ callID: String, callee: ZegoCallUser) {
        
    }
    func onOutgoingCallRejectedCauseBusy(_ callID: String, callee: ZegoCallUser) {
        
    }
    func onOutgoingCallDeclined(_ callID: String, callee: ZegoCallUser) {
        
    }
    func onIncomingCallTimeout(_ callID: String,  caller: ZegoCallUser){
        
    }
    func onOutgoingCallTimeout(_ callID: String, callees: [ZegoCallUser]) {
        
    }
}
